#include "freertos_timer.h"
#include <string.h>

/**
 * 将定时器插入激活链表（双向链表，按到期时间升序排列）
 * 类似FreeRTOS的prvAddTimerToActiveList，保证链表有序以提高效率
 */
static void prvAddTimerToActiveList(TimerManager_t* pxManager, Timer_t* pxTimer) {
    if (pxManager == NULL || pxTimer == NULL) return;

    Timer_t* pxIterator;

    // 链表为空时直接插入
    if (pxManager->pxActiveTimerList == NULL) {
        pxManager->pxActiveTimerList = pxTimer;
        pxTimer->pxNext = NULL;
        pxTimer->pxPrevious = NULL;
    } else {
        // 按到期时间升序插入（找到第一个到期时间更大的节点）
        pxIterator = pxManager->pxActiveTimerList;
        while (pxIterator != NULL && pxIterator->ulExpireTime <= pxTimer->ulExpireTime) {
            pxIterator = pxIterator->pxNext;
        }

        // 插入到pxIterator之前
        if (pxIterator == NULL) {
            // 插入到链表尾部
            Timer_t* pxLast = pxManager->pxActiveTimerList;
            while (pxLast->pxNext != NULL) {
                pxLast = pxLast->pxNext;
            }
            pxLast->pxNext = pxTimer;
            pxTimer->pxPrevious = pxLast;
            pxTimer->pxNext = NULL;
        } else {
            // 插入到中间或头部
            pxTimer->pxPrevious = pxIterator->pxPrevious;
            pxTimer->pxNext = pxIterator;
            if (pxIterator->pxPrevious != NULL) {
                pxIterator->pxPrevious->pxNext = pxTimer;
            } else {
                // 插入到头部
                pxManager->pxActiveTimerList = pxTimer;
            }
            pxIterator->pxPrevious = pxTimer;
        }
    }
}

/**
 * 将定时器从激活链表中移除
 */
static void prvRemoveTimerFromActiveList(TimerManager_t* pxManager, Timer_t* pxTimer) {
    if (pxManager == NULL || pxTimer == NULL || pxManager->pxActiveTimerList == NULL) return;

    // 处理前驱节点
    if (pxTimer->pxPrevious != NULL) {
        pxTimer->pxPrevious->pxNext = pxTimer->pxNext;
    } else {
        // 当前节点是头节点
        pxManager->pxActiveTimerList = pxTimer->pxNext;
    }

    // 处理后继节点
    if (pxTimer->pxNext != NULL) {
        pxTimer->pxNext->pxPrevious = pxTimer->pxPrevious;
    }

    // 清空链表指针
    pxTimer->pxNext = NULL;
    pxTimer->pxPrevious = NULL;
}

/**
 * 初始化定时器管理器
 */
void vTimerManagerInit(TimerManager_t* pxManager, uint32_t (*pxGetTickFunc)(void)) {
    if (pxManager == NULL || pxGetTickFunc == NULL) return;
    pxManager->pxActiveTimerList = NULL;
    pxManager->pxGetSystemTick = pxGetTickFunc;
    pxManager->ulCurrentTime = 0;
}

/**
 * 创建定时器
 */
void vTimerCreate(Timer_t* pxTimer,
                 uint32_t ulPeriod,
                 TimerMode eMode,
                 void* pvParameters,
                 TimerCallbackFunction_t pxCallback) {
    if (pxTimer == NULL || pxCallback == NULL || ulPeriod == 0) return;
    memset(pxTimer, 0, sizeof(Timer_t));
    pxTimer->pxCallbackFunction = pxCallback;
    pxTimer->pvParameters = pvParameters;
    pxTimer->ulTimerPeriod = ulPeriod;
    pxTimer->eTimerMode = eMode;
    pxTimer->eTimerState = TIMER_INACTIVE;
    pxTimer->bExpired = false;
}

/**
 * 启动定时器
 */
bool xTimerStart(TimerManager_t* pxManager, Timer_t* pxTimer, uint32_t ulStartDelay) {
    if (pxManager == NULL || pxTimer == NULL || pxManager->pxGetSystemTick == NULL) {
        return false;
    }

    // 计算到期时间：当前时间 + 启动延迟
    uint32_t ulCurrentTime = pxManager->pxGetSystemTick();
    pxTimer->ulExpireTime = ulCurrentTime + ulStartDelay;
    pxTimer->eTimerState = TIMER_ACTIVE;
    pxTimer->bExpired = false;

    // 加入激活链表（有序）
    prvAddTimerToActiveList(pxManager, pxTimer);
    return true;
}

/**
 * 停止定时器
 */
void vTimerStop(TimerManager_t* pxManager, Timer_t* pxTimer) {
    if (pxManager == NULL || pxTimer == NULL || pxTimer->eTimerState != TIMER_ACTIVE) {
        return;
    }

    // 从链表移除
    prvRemoveTimerFromActiveList(pxManager, pxTimer);
    pxTimer->eTimerState = TIMER_INACTIVE;
    pxTimer->bExpired = false;
}

/**
 * 检查定时器是否到期（处理32位时间溢出）
 */
static bool prvIsTimerExpired(Timer_t* pxTimer, uint32_t ulCurrentTime) {
    // 时间未溢出：当前时间 >= 到期时间 → 到期
    if (ulCurrentTime >= pxTimer->ulExpireTime) {
        return true;
    }
    // 时间溢出：当前时间 < 到期时间，但实际已溢出（如到期时间是0xFFFFFFFE，当前时间是1）
    // 此时差值为 (0xFFFFFFFF - 到期时间) + 当前时间 + 1 ≥ 周期 → 到期
    uint32_t ulDiff = (0xFFFFFFFF - pxTimer->ulExpireTime) + ulCurrentTime + 1;
    return (ulDiff >= pxTimer->ulTimerPeriod);
}

/**
 * 定时器处理函数（执行到期回调）
 * 类似FreeRTOS的定时器服务任务，在任务级执行回调
 */
void vTimerProcess(TimerManager_t* pxManager) {
    if (pxManager == NULL || pxManager->pxGetSystemTick == NULL) return;

    // 获取当前系统时间（缓存，减少回调调用）
    pxManager->ulCurrentTime = pxManager->pxGetSystemTick();

    // 遍历激活链表，处理到期的定时器
    Timer_t* pxCurrent = pxManager->pxActiveTimerList;
    while (pxCurrent != NULL) {
        // 保存下一个节点（防止回调中删除当前节点导致链表断裂）
        Timer_t* pxNext = pxCurrent->pxNext;

        if (pxCurrent->eTimerState == TIMER_ACTIVE && 
            prvIsTimerExpired(pxCurrent, pxManager->ulCurrentTime)) {

            // 标记为已到期
            pxCurrent->bExpired = true;

            // 执行回调函数（在当前任务/主循环中执行，非中断）
            if (pxCurrent->pxCallbackFunction != NULL) {
                pxCurrent->pxCallbackFunction(pxCurrent->pvParameters);
            }

            // 处理模式
            if (pxCurrent->eTimerMode == timerONE_SHOT) {
                // 单次模式：执行后停止
                vTimerStop(pxManager, pxCurrent);
            } else {
                // 周期模式：更新到期时间，重新加入链表
                prvRemoveTimerFromActiveList(pxManager, pxCurrent);
                pxCurrent->ulExpireTime = pxManager->ulCurrentTime + pxCurrent->ulTimerPeriod;
                prvAddTimerToActiveList(pxManager, pxCurrent);
                pxCurrent->bExpired = false;
            }
        }

        pxCurrent = pxNext;
    }
}